package com.iamalive;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Iterator;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;


import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xmlpull.v1.XmlSerializer;

import com.iamalive.LocalCache.InfoDetails;


import android.util.Xml;

public class XmlReaderWriter {
	
	public XmlReaderWriter() {
		// TODO Auto-generated constructor stub
	}
	
	/**
	  * Getting XML DOM element
	  * @param XML string
	* */
	public static Document getDomElement(String xml){
	  Document doc = null;
	  DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
	  try {
	 
	   DocumentBuilder db = dbf.newDocumentBuilder();
	 
	   InputSource is = new InputSource();
	          is.setCharacterStream(new StringReader(xml));
	          doc = db.parse(is); 
	 
	   } catch (ParserConfigurationException e) {
		   return null;
	   } catch (SAXException e) {
		   return null;
	   } catch (IOException e) {
		   return null;
	   }	 
	   return doc;
	}
	
	/** Getting node value
	   * @param elem element
	   */
	public static String getElementValue(Node elem) {
	      Node child;
	      if( elem != null){
	          if (elem.hasChildNodes()){
	              for( child = elem.getFirstChild(); child != null; child = child.getNextSibling() ){
	                  if( child.getNodeType() == Node.TEXT_NODE  ){
	                      return child.getNodeValue();
	                  }
	              }
	          }
	      }
	      return "";
	}
	
	public static int extractMessages(Element elem, ArrayList<String> messagesList) {
		int noOfMessages = 0;
		if(elem == null) {
			return noOfMessages;
		}
		
		NodeList elementList = elem.getElementsByTagName(new String("messages"));
		Node messagesElement = elementList.item(0);
		
		if(messagesElement == null) {
			return noOfMessages;
		}
		
		Node child;
		if (messagesElement.hasChildNodes()){
			for(child = messagesElement.getFirstChild(); child != null; child = child.getNextSibling() ) {
				if(child.getNodeName().equals("message")) {
					messagesList.add(getElementValue(child));
					noOfMessages++;
				}
			}
		}

		return noOfMessages;
	}
	
	/**
	   * Getting node value
	   * @param Element node
	   * @param key string
	* */
	public final String getValue(Element item, String str) {  
	   NodeList n = item.getElementsByTagName(str);  
	   return this.getElementValue(n.item(0));
	}
	
	public final String getElementAttribute(Element item, String attribName){
		   return item.getAttribute(attribName);   
	}
	
	/*
	 * <registeruser>
        <source>app</source>
        <details>
                <emailid>kamal.nandan@gmail.com</emailid>
                <password>kamal</password>
                <name>Kamal Nandan</name>
                <gender>M</gender>
                <address>1260, Sec 29, Noida</address>
                <city>Noida</city>
                <state>UP</state>
                <country>india</country>
                <zip>201310</zip>
                <phone>9971295647</phone>
                <dob>1981-12-22</dob>
        </details>
		</registeruser>
	 */
	public static String assembleRegisterUserRequest(String emailId, String password, String name, String gender,
			String address, String city, String state, String country, String zip, String phone, String dob) {
		XmlSerializer serializer = Xml.newSerializer();
		StringWriter writer = new StringWriter();
		try {
			serializer.setOutput(writer);
			serializer.startDocument("UTF-8", true);
			serializer.startTag("", "registeruser");
			serializer.startTag("", "source");
			serializer.text("android-app");
			serializer.endTag("", "source");
			serializer.startTag("", "details");
			serializer.startTag("", "emailid");
			serializer.text(emailId);
			serializer.endTag("", "emailid");
			serializer.startTag("", "password");
			serializer.text(password);
			serializer.endTag("", "password");
			serializer.startTag("", "name");
			serializer.text(name);
			serializer.endTag("", "name");
			serializer.startTag("", "gender");
			serializer.text(gender);
			serializer.endTag("", "gender");
			serializer.startTag("", "address");
			serializer.text(address);
			serializer.endTag("", "address");
			serializer.startTag("", "city");
			serializer.text(city);
			serializer.endTag("", "city");
			serializer.startTag("", "state");
			serializer.text(state);
			serializer.endTag("", "state");
			serializer.startTag("", "country");
			serializer.text(country);
			serializer.endTag("", "country");
			serializer.startTag("", "zip");
			serializer.text(zip);
			serializer.endTag("", "zip");
			serializer.startTag("", "phone");
			serializer.text(phone);
			serializer.endTag("", "phone");
			serializer.startTag("", "dob");
			serializer.text(dob);
			serializer.endTag("", "dob");
			serializer.endTag("", "details");
			serializer.endTag("", "registeruser");
			serializer.endDocument();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		String retStr = writer.toString();
		return retStr;
	}
	
	/*
	 * In case of success....
	 * 	<registerresponse xmlns:ns="iamalive" ns:status="0">
	 * 		<messages></messages>
	 * 		<userid></userid>
	 * </registerresponse>		
	*
	* In case of failure
	* <registerresponse xmlns:ns="iamalive" ns:status="-1">
	* 	<messages>
	* 		<message>The user id londonnode@gmail.com is already registered</message>
	* 	</messages>
	* </registerresponse>
	* 	
	 */
	public static boolean parseRegisterUserResponse(String xmlresponseString, ArrayList<String> messageList) {
		Document doc = getDomElement(xmlresponseString);
		if(doc == null) {
			messageList.add("XML response received is corrupt");
			return false;
		}
		
		Element rootEle = doc.getDocumentElement();

		String respCode = rootEle.getAttribute("ns:status");

		String nodeName = rootEle.getNodeName();
		
		if(false == respCode.equals("0")) {
			if(0 >= extractMessages(rootEle, messageList)) {
				messageList.add("Registration failed because of unknown reason"); //TODO: Fix this
			}
			return false;
		}
		
		return true;
	}

	
	/*
	 * <updateuserdetails>
        <emailid>kamal.nandan@gmail.com</emailid>
        <tokenid>1234</tokenid>
        <detailstoupdate>
                <emailid>hello.kr.dev@gmail.com</emailid>
                <password>sdasdsa</password>
                <address>sdadsf</address>
                <city>mumbai</city>
                <state>maharashtra</state>
                <country>India</country>
                <zip>110091</zip>
                <phone>99712-95647</phone>
        </detailstoupdate>
		</updateuserdetails>
	 */
	public static String assembleUpdateUserDetailsRequest(String emailId, String tokenId, String password, String name,
			String address, String city, String state, String country, String zip, String phone) {
		XmlSerializer serializer = Xml.newSerializer();
		StringWriter writer = new StringWriter();
		try {
			serializer.setOutput(writer);
			serializer.startDocument("UTF-8", true);
			serializer.startTag("", "updateuserdetails");
			serializer.startTag("", "source");
			serializer.text("android-app");
			serializer.endTag("", "source");
			serializer.startTag("", "emailid");
			serializer.text(emailId);
			serializer.endTag("", "emailid");
			serializer.startTag("", "tokenid");
			serializer.text(tokenId);
			serializer.endTag("", "tokenid");
			serializer.startTag("", "detailstoupdate");
			serializer.startTag("", "password");
			serializer.text(password);
			serializer.endTag("", "password");
			serializer.startTag("", "name");
			serializer.text(name);
			serializer.endTag("", "name");
			serializer.startTag("", "address");
			serializer.text(address);
			serializer.endTag("", "address");
			serializer.startTag("", "city");
			serializer.text(city);
			serializer.endTag("", "city");
			serializer.startTag("", "state");
			serializer.text(state);
			serializer.endTag("", "state");
			serializer.startTag("", "country");
			serializer.text(country);
			serializer.endTag("", "country");
			serializer.startTag("", "zip");
			serializer.text(zip);
			serializer.endTag("", "zip");
			serializer.startTag("", "phone");
			serializer.text(phone);
			serializer.endTag("", "phone");
			serializer.endTag("", "detailstoupdate");
			serializer.endTag("", "updateuserdetails");
			serializer.endDocument();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		String retStr = writer.toString();
		return retStr;
	}
	
	/*
	 * <login>
       	<source>web-browser</source>
        <details>
        	<emailid>kamal.nandan@gmail.com</emailid>
			<password>kamal</password>
        </details>
		</login>
	 */
	public static String assembleLoginRequest(final String emailId, final String password) {
		XmlSerializer serializer = Xml.newSerializer();
		StringWriter writer = new StringWriter();
		try {
			serializer.setOutput(writer);
			serializer.startDocument("UTF-8", true);
			serializer.startTag("", "login");
			serializer.startTag("", "source");
			serializer.text("android-app");
			serializer.endTag("", "source");
			serializer.startTag("", "details");
			serializer.startTag("", "emailid");
			serializer.text(emailId);
			serializer.endTag("", "emailid");
			serializer.startTag("", "password");
			serializer.text(password);
			serializer.endTag("", "password");
			serializer.endTag("", "details");
			serializer.endTag("", "login");
			serializer.endDocument();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		String retStr = writer.toString();
		return retStr;
	}
	
	
	/*
	 * <loginresponse status="0">
        <emailid>kamal.nandan@gmail.com</emailid>
        <tokenid>1</tokenid>
        <messages>
                <message>xxx</message>
                <message>yyy</message>
        </messages>
		</loginresponse>
	 */
	public static boolean parseLoginResponse(String xmlresponseString, ArrayList<String> messageList) {
		Document doc = getDomElement(xmlresponseString);
		if(doc == null) {
			messageList.add("XML response received is corrupt");
			return false;
		}
		
		Element rootEle = doc.getDocumentElement();

		String respCode = rootEle.getAttribute("ns:status");

		
		String nodeName = rootEle.getNodeName();
		
		if(respCode.equals("0")) {
			NodeList elementList = rootEle.getElementsByTagName("tokenid");
			String tokenId = getElementValue(elementList.item(0));
			if(tokenId.trim().equals("")) {
				messageList.add("Token ID not found in the response; perhaps data is corrupt");
				return false;
			}
			LocalCache.getSingleInstance().mTokenId = tokenId;
			LocalCache.getSingleInstance().mUserValidated = true;
		} else {
			LocalCache.getSingleInstance().mTokenId = "";
			LocalCache.getSingleInstance().mUserValidated = false;
			//parse and extract messages from the list			
			if(0 >= extractMessages(rootEle, messageList)) {
				return false;
			}
		}

		return true;
	}
	
	/*
	 * <logout>
        <details>
                <emailid>kamal.nandan@gmail.com</emailid>
                <tokenid>123</tokenid>
        </details>
</logout>

	 */
	public static String assembleLogoutRequest(final String emailId, final String tokenid) {
		XmlSerializer serializer = Xml.newSerializer();
		StringWriter writer = new StringWriter();
		try {
			serializer.setOutput(writer);
			serializer.startDocument("UTF-8", true);
			serializer.startTag("", "logout");
			serializer.startTag("", "source");
			serializer.text("android-app");
			serializer.endTag("", "source");
			serializer.startTag("", "details");
			serializer.startTag("", "emailid");
			serializer.text(emailId);
			serializer.endTag("", "emailid");
			serializer.startTag("", "tokenid");
			serializer.text(tokenid);
			serializer.endTag("", "tokenid");
			serializer.endTag("", "details");
			serializer.endTag("", "logout");
			serializer.endDocument();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		String retStr = writer.toString();
		return retStr;
	}
	
	/*
	 * 	/*
		 * <fetchuserdata>
	        <source>web-browser</source>
	        <emailid>kamal.nandan@gmail.com</emailid>
	        <tokenid>123</tokenid>
			</fetchuserdata>
	
		 */
	
	public static String assembleFetchUserDataRequest(String emailId, String tokenId) {
		XmlSerializer serializer = Xml.newSerializer();
		StringWriter writer = new StringWriter();
		try {
			serializer.setOutput(writer);
			serializer.startDocument("UTF-8", true);
			serializer.startTag("", "fetchuserdata");
			serializer.startTag("", "source");
			serializer.text("android-app");
			serializer.endTag("", "source");
			serializer.startTag("", "emailid");
			serializer.text(emailId);
			serializer.endTag("", "emailid");
			serializer.startTag("", "tokenid");
			serializer.text(tokenId);
			serializer.endTag("", "tokenid");
			serializer.endTag("", "fetchuserdata");
			serializer.endDocument();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		String retStr = writer.toString();
		return retStr;

	}
	
 
	
	/*
	 * <addinfo>
        <source>web-browser</source>
        <emailid>kamal.nandan@gmail.com</emailid>
        <tokenid>123</tokenid>
        <details>
                <info>LIC policy no: 123456, vasant vihar</info>
                <media>0</media>
                <expirydate>2031-12-22</expirydate>
                <ttl>100</ttl>
        </details>
		</addinfo>

	 */
	public static String assembleAddInfoRequest(String emailId, String tokenId, InfoDetails infoDetails) {
		XmlSerializer serializer = Xml.newSerializer();
		StringWriter writer = new StringWriter();
		try {
			serializer.setOutput(writer);
			serializer.startDocument("UTF-8", true);
			serializer.startTag("", "addinfo");
			serializer.startTag("", "source");
			serializer.text("android-app");
			serializer.endTag("", "source");
			serializer.startTag("", "emailid");
			serializer.text(emailId);
			serializer.endTag("", "emailid");
			serializer.startTag("", "tokenid");
			serializer.text(tokenId);
			serializer.endTag("", "tokenid");
			serializer.startTag("", "details");
			serializer.startTag("", "info");
			serializer.text(infoDetails.infoBody);
			serializer.endTag("", "info");
			serializer.startTag("", "media");
			serializer.text(infoDetails.media.toString());
			serializer.endTag("", "media");
			serializer.startTag("", "ttl");
			serializer.text(Long.toString(infoDetails.ttl));
			serializer.endTag("", "ttl");
			serializer.endTag("", "details");
			serializer.endTag("", "addinfo");
			serializer.endDocument();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		String retStr = writer.toString();
		return retStr;
		
	}
	
	/*
	 * <updateinfo>
        <source>web-browser</source>
        <emailid>kamal.nandan@gmail.com</emailid>
        <tokenid>123</tokenid>
        <infoid>1234</infoid>
        <details>
                <info>LIC policy no: 123456, vasant vihar</info>
                <media>0</media>
                <expirydate>2031-12-22</expirydate>
                <ttl>100</ttl>
        </details>
	</updateinfo>

	 */
	public static String assembleUpdateInfoRequest(String emailId, String tokenId, long infoId, String info, long ttl) {
		XmlSerializer serializer = Xml.newSerializer();
		StringWriter writer = new StringWriter();
		try {
			serializer.setOutput(writer);
			serializer.startDocument("UTF-8", true);
			serializer.startTag("", "updateinfo");
			serializer.startTag("", "source");
			serializer.text("android-app");
			serializer.endTag("", "source");
			serializer.startTag("", "emailid");
			serializer.text(emailId);
			serializer.endTag("", "emailid");
			serializer.startTag("", "tokenid");
			serializer.text(tokenId);
			serializer.endTag("", "tokenid");
			serializer.startTag("", "infoid");
			serializer.text(Long.toString(infoId));
			serializer.endTag("", "infoid");
			serializer.startTag("", "details");
			serializer.startTag("", "info");
			serializer.text(info);
			serializer.endTag("", "info");
			serializer.startTag("", "ttl");
			serializer.text(Long.toString(ttl));
			serializer.endTag("", "ttl");
			serializer.endTag("", "details");
			serializer.endTag("", "updateinfo");
			serializer.endDocument();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		String retStr = writer.toString();
		return retStr;
		
	}
	
	/*
	 * <deleteinfo>
        <source>web-browser</source>
        <emailid>kamal.nandan@gmail.com</emailid>
        <tokenid>123</tokenid>
        <infoid>1234</infoid>
		</deleteinfo>
	 */
	public static String assembleDeleteInfoRequest(String emailId, String tokenId, long infoId) {
		XmlSerializer serializer = Xml.newSerializer();
		StringWriter writer = new StringWriter();
		try {
			serializer.setOutput(writer);
			serializer.startDocument("UTF-8", true);
			serializer.startTag("", "deleteinfo");
			serializer.startTag("", "source");
			serializer.text("android-app");
			serializer.endTag("", "source");
			serializer.startTag("", "emailid");
			serializer.text(emailId);
			serializer.endTag("", "emailid");
			serializer.startTag("", "tokenid");
			serializer.text(tokenId);
			serializer.endTag("", "tokenid");
			serializer.startTag("", "infoid");
			serializer.text(Long.toString(infoId));
			serializer.endTag("", "infoid");
			serializer.endTag("", "deleteinfo");
			serializer.endDocument();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		String retStr = writer.toString();
		return retStr;
	}

	/*
	 * <addrecipient>
        <emailid>kn@gmail.com</emailid>
        <tokenid>123</tokenid>
        <details>
        	<name>KN</name>
        	<emailid> kn@gmail.com</emailid>
        	<phone>9540009</phone>
        	<address>1260, sec 29, noida</address>
        	<relationship>brother</relationship>
        </details>
	</addrecipient>
	 */
	public static String assembleAddRecipientRequest(String emailId, String tokenId, String recipientName, String recipientEmailId,
			String recipientPhone, String recipientAddress, String recipientRelationShip) {
		XmlSerializer serializer = Xml.newSerializer();
		StringWriter writer = new StringWriter();
		try {
			serializer.setOutput(writer);
			serializer.startDocument("UTF-8", true);
			serializer.startTag("", "addrecipient");
			serializer.startTag("", "source");
			serializer.text("android-app");
			serializer.endTag("", "source");
			serializer.startTag("", "emailid");
			serializer.text(emailId);
			serializer.endTag("", "emailid");
			serializer.startTag("", "tokenid");
			serializer.text(tokenId);
			serializer.endTag("", "tokenid");
			serializer.startTag("", "details");
			serializer.startTag("", "name");
			serializer.text(recipientName);
			serializer.endTag("", "name");			
			serializer.startTag("", "emailid");
			serializer.text(recipientEmailId);
			serializer.endTag("", "emailid");
			serializer.startTag("", "phone");
			serializer.text(recipientPhone);
			serializer.endTag("", "phone");
			serializer.startTag("", "address");
			serializer.text(recipientAddress);
			serializer.endTag("", "address");
			serializer.startTag("", "relationship");
			serializer.text(recipientRelationShip);
			serializer.endTag("", "relationship");			
			serializer.endTag("", "details");			
			serializer.endTag("", "addrecipient");
			serializer.endDocument();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		String retStr = writer.toString();
		return retStr;
	}
	
	/*
	 * <updaterecipient>
        <emailid>kn@gmail.com</emailid>
        <tokenid>123</tokenid>
        <recipientid>123</recipientid>
        <details>
                <name> kn</name>
                <emailid>dss@gmail.com</emailid>
                <phone>9971295647</phone>
                <address>sdkadm</address>
                <relationship>dsfkf</relationship>
        </details>
	</updaterecipient>
	 */
	public static String assembleUpdateRecipientRequest(String emailId, String tokenId, String recipientId, 
			String recipientName, String recipientEmailId,
			String recipientPhone, String recipientAddress, String recipientRelationShip) {
		XmlSerializer serializer = Xml.newSerializer();
		StringWriter writer = new StringWriter();
		try {
			serializer.setOutput(writer);
			serializer.startDocument("UTF-8", true);
			serializer.startTag("", "updaterecipient");
			serializer.startTag("", "source");
			serializer.text("android-app");
			serializer.endTag("", "source");
			serializer.startTag("", "emailid");
			serializer.text(emailId);
			serializer.endTag("", "emailid");
			serializer.startTag("", "tokenid");
			serializer.text(tokenId);
			serializer.endTag("", "tokenid");
			serializer.startTag("", "recipientid");
			serializer.text(recipientId);
			serializer.endTag("", "recipientid");			
			serializer.startTag("", "details");
			serializer.startTag("", "name");
			serializer.text(recipientName);
			serializer.endTag("", "name");			
			serializer.startTag("", "emailid");
			serializer.text(recipientEmailId);
			serializer.endTag("", "emailid");
			serializer.startTag("", "phone");
			serializer.text(recipientPhone);
			serializer.endTag("", "phone");
			serializer.startTag("", "address");
			serializer.text(recipientAddress);
			serializer.endTag("", "address");
			serializer.startTag("", "relationship");
			serializer.text(recipientRelationShip);
			serializer.endTag("", "relationship");			
			serializer.endTag("", "details");			
			serializer.endTag("", "updaterecipient");
			serializer.endDocument();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		String retStr = writer.toString();
		return retStr;
	}
	
	
	/*
	 * <deleterecipient>
        <emailid>kn@gmail.com</emailid>
        <tokenid>123</tokenid>
        <recipientid>1234</recipientid>
	</deleterecipient>
	 */
	public static String assembleDeleteRecipientRequest(String emailId, String tokenId, long recipientId) {
		XmlSerializer serializer = Xml.newSerializer();
		StringWriter writer = new StringWriter();
		try {
			serializer.setOutput(writer);
			serializer.startDocument("UTF-8", true);
			serializer.startTag("", "deleterecipient");
			serializer.startTag("", "source");
			serializer.text("android-app");
			serializer.endTag("", "source");
			serializer.startTag("", "emailid");
			serializer.text(emailId);
			serializer.endTag("", "emailid");
			serializer.startTag("", "tokenid");
			serializer.text(tokenId);
			serializer.endTag("", "tokenid");
			serializer.startTag("", "recipientid");
			serializer.text(Long.toString(recipientId));
			serializer.endTag("", "recipientid");
			serializer.endTag("", "deleterecipient");
			serializer.endDocument();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		String retStr = writer.toString();
		return retStr;
	}
	
	/*
	 * <addinforecipients>
        <source>web-browser</source>
        <emailid>kamal.nandan@gmail.com</emailid>
        <tokenid>123</tokenid>
        <infoid>1234</infoid>
        <recipients>
                <recipient>
                        <id> 123 </id>
                </recipient>
        </recipients>
	</addinforecipients>
	 */
	public static String assembleAddInfoRecipientRequest(String emailId, String tokenId, long infoId, 
			ArrayList<Long> recipientIds) {
		XmlSerializer serializer = Xml.newSerializer();
		StringWriter writer = new StringWriter();
		try {
			serializer.setOutput(writer);
			serializer.startDocument("UTF-8", true);
			serializer.startTag("", "addinforecipients");
			serializer.startTag("", "source");
			serializer.text("android-app");
			serializer.endTag("", "source");
			serializer.startTag("", "emailid");
			serializer.text(emailId);
			serializer.endTag("", "emailid");
			serializer.startTag("", "tokenid");
			serializer.text(tokenId);
			serializer.endTag("", "tokenid");
			serializer.startTag("", "recipients");
					
			Iterator<Long> it = recipientIds.iterator();
			while (it.hasNext()) {
				String recipientId = Long.toString(it.next());
				serializer.startTag("", "recipient");
				serializer.startTag("", "id");
				serializer.text(recipientId);
				serializer.startTag("", "id");
				serializer.endTag("", "recipient");				
			}
			
			serializer.endTag("", "recipients");
			serializer.endTag("", "addinforecipients");
			serializer.endDocument();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		
		String retStr = writer.toString();
		return retStr;
	}
}


